package com.pipe.connector.actor;

import com.pipe.exception.ProtocolCodecException;
import com.pipe.exception.SessionException;
import com.pipe.protocol.BasePackage;
import com.pipe.protocol.login.OkAndEofPacket;
import com.pipe.protocol.query.*;
import com.pipe.util.MyBytebufUtil;
import com.sun.scenario.effect.impl.prism.PrImage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Kiven
 */
public class QueryResultActor {
    private static Logger LOG = LoggerFactory.getLogger(QueryResultActor.class);

    private QueryStatus queryStatus = QueryStatus.FIELD_COUNT;
    private long fieldCount = 0;
    private List<ColumnDefinition41Package> columnDefinitionList = new LinkedList<>();
    private List<ResultsetRowPacakge> resultList = new LinkedList<>();

    private static int MIN_READABLE_DATA = 5;
    private static int TAIL = 0xfe;

    TableMetaInfo handler(BasePackage basePackage) throws ProtocolCodecException {
        if (queryStatus == QueryStatus.FIELD_COUNT){
            FieldCountPackage fieldCountPackage = FieldCountPackage.build(basePackage.getPayLoadByteBuf());
            this.fieldCount = fieldCountPackage.getFieldCount();
            queryStatus = QueryStatus.FIELD;
            return null;
        }
        if (queryStatus == QueryStatus.FIELD){
            ColumnDefinition41Package columnDefinition41Package = ColumnDefinition41Package.build(basePackage.getPayLoadByteBuf());
            columnDefinitionList.add(columnDefinition41Package);
            fieldCount--;
            if (fieldCount == 0){
                queryStatus = QueryStatus.EOF;
            }
            return null;
        }
        if (queryStatus == QueryStatus.EOF){
            OkAndEofPacket okAndEofPacket = OkAndEofPacket.shortBuild(basePackage.getPayLoadByteBuf());
            if (okAndEofPacket.isEofHead()){
                queryStatus = QueryStatus.ROW;
                return null;
            } else {
                LOG.info("[QUERY] - Wrong package recieved!");
            }
        }
        if (queryStatus == QueryStatus.ROW){
            if (basePackage.getPayLoadByteBuf().readableBytes() <= MIN_READABLE_DATA){
                short header = basePackage.getPayLoadByteBuf().getUnsignedByte(basePackage.getPayLoadByteBuf().readerIndex());
                if (header == TAIL){
                    LOG.info("[QUERY] - Tail eof package reached!");
                    LOG.info("[QUERY] - columnDefinitionList response: " + columnDefinitionList.toString());
                    LOG.info("[QUERY] - resultList response: " + resultList.toString());
                    TableMetaInfo tableMetaInfo = new TableMetaInfo(new LinkedList<>(columnDefinitionList), new LinkedList<>(resultList));
                    columnDefinitionList.clear();
                    resultList.clear();
                    queryStatus = QueryStatus.FIELD_COUNT;
                    return tableMetaInfo;
                }
            }
            ResultsetRowPacakge resultsetRowPacakge = ResultsetRowPacakge.build(basePackage.getPayLoadByteBuf());
            resultList.add(resultsetRowPacakge);
            return null;
        }
        LOG.warn("[QUERY] - Unknown status or package!");
        throw new ProtocolCodecException("[QUERY] - Unknown status or package!");
    }

    private static enum QueryStatus{
        /***/
        FIELD_COUNT,
        /***/
        FIELD,
        /***/
        EOF,
        /***/
        ROW;
    }
}